﻿using EnvDTE;

namespace PropertyAddin
{
	#region Interface IStruct
	interface IStruct
	{
		CodeElements Members { get; }
		CodeElements Bases { get; }
		string Name { get; }
		TextPoint StartPoint { get; }

		CodeProperty AddProperty(ClassField field, bool createGetter, bool createSetter, object pos);
		CodeFunction AddConstructor(object pos);
	}
	#endregion Interface IStruct

	#region Class StructStructure
	/// <summary>
	/// StructStructure: Contains the structure of a struct.
	/// </summary>
	class StructStructure : IStruct
	{
		#region Private Members
		private CodeStruct m_ElemStruct;
		#endregion Private Members

		#region Constructors
		public StructStructure(CodeStruct elem)
		{
			m_ElemStruct = elem;
		}
		#endregion Constructors

		#region IStruct Members
		/// <summary>
		/// Members of the struct.
		/// </summary>
		public CodeElements Members
		{
			get { return m_ElemStruct.Members; }
		}

		/// <summary>
		/// 
		/// </summary>
		public CodeElements Bases
		{
			get { return m_ElemStruct.Bases; }
		}

		/// <summary>
		/// Name of the struct.
		/// </summary>
		public string Name
		{
			get { return m_ElemStruct.Name; }
		}

		/// <summary>
		/// Gets the start text point of the struct.
		/// </summary>
		public TextPoint StartPoint
		{
			get { return m_ElemStruct.StartPoint; }
		}

		/// <summary>
		/// Adds the property to the struct for that field with a getter and a setter according to the
		/// boolean parameters at the defined position.
		/// </summary>
		/// <param name="field"></param>
		/// <param name="createGetter"></param>
		/// <param name="createSetter"></param>
		/// <param name="pos"></param>
		/// <returns></returns>
		public CodeProperty AddProperty(ClassField field, bool createGetter, bool createSetter,
			object pos)
		{
			string getterName = createGetter ? field.PropertyName : null;
			string setterName = createSetter ? field.PropertyName : null;
			CodeProperty property = m_ElemStruct.AddProperty(getterName, setterName,
				field.Variable.Type.AsString, pos, vsCMAccess.vsCMAccessPublic, null);

			field.Property = property;
			return property;
		}

		/// <summary>
		/// Adds a constructor to the struct with these parameters at that defined position.
		/// </summary>
		/// <param name="pos"></param>
		/// <returns></returns>
		public CodeFunction AddConstructor(object pos)
		{
			return m_ElemStruct.AddFunction(m_ElemStruct.Name, vsCMFunction.vsCMFunctionConstructor, null,
				pos, vsCMAccess.vsCMAccessPublic, null);
		}
		#endregion IStruct Members
	}
	#endregion Class StructStructure

	#region Class ClassStructure
	/// <summary>
	/// ClassStructure: Contains the structure of a class.
	/// </summary>
	class ClassStructure : IStruct
	{
		#region Private Members
		private CodeClass m_ElemClass;
		#endregion Private Members

		#region Constructors
		public ClassStructure(CodeClass elem)
		{
			m_ElemClass = elem;
		}
		#endregion Constructors

		#region IStruct Members
		/// <summary>
		/// Members of the class.
		/// </summary>
		public CodeElements Members
		{
			get { return m_ElemClass.Members; }
		}

		/// <summary>
		/// Name of the class.
		/// </summary>
		public string Name
		{
			get { return m_ElemClass.Name; }
		}

		/// <summary>
		/// 
		/// </summary>
		public CodeElements Bases
		{
			get { return m_ElemClass.Bases; }
		}

		/// <summary>
		/// Gets the start text point of the class.
		/// </summary>
		public TextPoint StartPoint
		{
			get { return m_ElemClass.StartPoint; }
		}

		/// <summary>
		/// Adds the property to the class for that field with a getter and a setter according to the
		/// boolean parameters at the defined position.
		/// </summary>
		/// <param name="field"></param>
		/// <param name="createGetter"></param>
		/// <param name="createSetter"></param>
		/// <param name="pos"></param>
		/// <returns></returns>
		public CodeProperty AddProperty(ClassField field, bool createGetter, bool createSetter,
			object pos)
		{
			string getterName = createGetter ? field.PropertyName : null;
			string setterName = createSetter ? field.PropertyName : null;
			CodeProperty property = m_ElemClass.AddProperty(getterName, setterName, field.Variable.Type.AsString, pos,
				vsCMAccess.vsCMAccessPublic, null);

			field.Property = property;
			return property;
		}

		/// <summary>
		/// Adds a constructor to the class with these parameters at that defined position.
		/// </summary>
		/// <param name="pos"></param>
		/// <returns></returns>
		public CodeFunction AddConstructor(object pos)
		{
			return m_ElemClass.AddFunction(m_ElemClass.Name, vsCMFunction.vsCMFunctionConstructor, null,
				pos, vsCMAccess.vsCMAccessPublic, null);
		}
		#endregion IStruct Members
	}
	#endregion Class ClassStructure
}
